
#include <cstdlib>
#include <iostream>
#include <string>
#include "Lfsr.h"
#include "MatrixTests.h"
#include "LfsrTests.h"
#include "Algebra.h"
#include "AlgebraFactory.h"

using namespace std;

const int defaultSequenceSize = 84;
const string defaultOutputName = "sequence.bin";
const string defaultTableName = "tables20.bin";

void printUsage()
{
	cout << "USAGE:" << endl
		<< "sequence.exe [PARAMETERS]" << endl
		<< "  -r --- Explore periods of LFSRs"  << endl
		<< "  -m --- Explore periods of matrices"  << endl
		<< "  -t FILE-NAME --- path to tables file"  << endl
		<< "  -s SIZE --- Size of sequence to generate (conflicts with -r and -m, default is " << defaultSequenceSize << ")" << endl
		<< "  -o FILE-NAME -- output filename (conflicts with -r and -m, default is \"" << defaultOutputName << "\")" << endl;
}
int main(int argc, char* argv[])
{
	bool bMatrix = false;
	bool bLfsr = false;
	bool bGenerate = false;
	string outputFileName = defaultOutputName;
	string tableFileName = defaultTableName;
	int seqSize = defaultSequenceSize;
	for(int i = 1; i < argc; i++)
	{
		if(string(argv[i]) == "-r")
		{
			bLfsr = true;
		}
		else if(string(argv[i]) == "-m")
		{
			bMatrix = true;
		}
		else if(string(argv[i]) == "-s")
		{
			bGenerate = true;
			if(i + 1 < argc)
			{
				seqSize = atoi(argv[i + 1]);
				if(seqSize == 0)
				{
					seqSize = defaultSequenceSize;
				}
				i++;
				bGenerate = true;
			}
		}
		else if(string(argv[i]) == "-t")
		{
			tableFileName = string(argv[i + 1]);
		}
		else if(string(argv[i]) == "-o")
		{
			if(i + 1 < argc)
			{
				outputFileName = string(argv[i + 1]);
				i++;
				bGenerate = true;
			}
		}
	}
	if(!bGenerate && !bMatrix && !bLfsr || bGenerate && (bMatrix || bLfsr))
	{
		printUsage();
	}
	else
	{
		IAlgebra *algebra = AlgebraFactory::CreateAlgebra(tableFileName);
		if(algebra == 0)
		{
			cerr << "Failed to load operation tables";
			return 0;
		}
		if(bGenerate)
		{
			if(LfsrTests::generate(algebra, seqSize, outputFileName))
			{
				cout << "sequence has been written to \"" << outputFileName << "\"";
			}
		}
		else
		{
			if(bLfsr)
				LfsrTests::defaultTest(algebra);
			if(bMatrix)
				MatrixTests::defaultTest(algebra);
		}
	}
	return 0;
}